package network.netty.coding;

import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.ByteToMessageDecoder;

import java.util.List;

/**
 * <p>
 * 自定义解码器，解决黏包、拆包
 * 黏包：TCP在发送数据的时候，数据大小不确定，数据太大的时候可能会把数据拆分成多个包后发送。而接收端不知道一次接收多少数据，
 * 可能一次就接收到多个包数据，黏在了一起。
 * Netty实现的黏包、拆包解决方案
 * - FixedLengthFrameDecoder 定长读取
 * - LineBasedFrameDecoder 按行读取
 * - DelimiterBaseFrameDecoder 按自定义分隔符读取
 * - LengthFieldBasedFrameDecoder 将数据包的长度作为头部传输，接收得到长度后按长度读取
 * </p>
 *
 * @author LovelyBigDuck
 * @date 2021/5/29 19:55
 */
public class ByteToChatMessageDecoder extends ByteToMessageDecoder {
    @Override
    protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
        if (in == null) {
            System.out.println("接收数据失败。。。");
            return;
        }
        // 自定义解码器规定：先传输数据长度，4字节
        if (in.readableBytes() <= 4) {
            System.out.println("数据长度不匹配。。。");
            return;
        }
        in.markReaderIndex();
        int len = in.readInt();
        if (in.readableBytes() < len) {
            in.resetReaderIndex();
            return;
        }
        byte[] bytes = new byte[len];
        in.readBytes(bytes);
        String json = new String(bytes);
        in.markReaderIndex();
        // 将处理后的数据交友handler链中下一个处理
        out.add(json);
    }
}
